import sys
import pandas as pd  
import serial  
import binascii 
import time
import struct
import os
import configparser
import random
from tkinter import messagebox 
import numpy as np  
from PIL import Image  
import pytesseract
# import get_current
import uiautomator2 as u2
import rtc_time
import time
from datetime import datetime
import download
import os
import subprocess

# from pywinauto import Application
# from pywinauto.findwindows import find_window  # 确保导入find_window函数

pytesseract.pytesseract.tesseract_cmd = r"C:\\Program Files\\Tesseract-OCR\\tesseract.exe"

class INI:
    def __init__(self): 
        self.config = configparser.ConfigParser() 
        self.com_port = ''
        self.baudrate = ''
        self.directory = ''
        
        
    def ini_read(self,config_file):
        self.config.read(config_file)  
        # 获取默认部分的设置  
        default_settings = self.config['DEFAULT']  
        self.com_port = default_settings.get("com")
        self.baudrate = default_settings.get("baudrate")
        self.directory = default_settings.get("directory")
        self.debug = default_settings.get("debug")

    def ini_write(self,config_file,com_port,baudrate,directory):
        # 手动输入参数
        baudrate = '115200'
        self.config['DEFAULT'] = {}
        self.com_port = self.config['DEFAULT']['com'] = com_port
        self.baudrate = self.config['DEFAULT']['baudrate'] = baudrate
        self.directory = self.config['DEFAULT']['directory'] = directory
        self.debug = self.config['DEFAULT']['debug'] = '0'
        # 保存INI文件  
        with open(config_file, 'w') as configfile:  
            self.config.write(configfile)  

def filter_duplicate_rows(df):
    # print(df)
    # 假设我们关注'Column1'和'Column2'两列来判断重复  
    subset_columns = ['步骤']  
    
    # 将关注的列转换为一个可用于分组和标记的键  
    df['group_key'] = df[subset_columns].apply(tuple, axis=1)  
    
    # 使用字典来记录每个组的一个随机索引  
    # 注意：这里我们使用了默认字典来自动处理新键的插入  
    selected_indices = {}  
    for key, group in df.groupby('group_key'):  
        # 从每个组中随机选择一个索引  
        selected_index = np.random.choice(group.index)  
        selected_indices[key] = selected_index  
    
    # 使用记录的索引来选择行  
    # 我们使用isin()和map()的组合来找出我们要保留的行  
    result_df = df[df.index.isin(df['group_key'].map(selected_indices))]  
    
    # 清理辅助列  
    del df['group_key']  
    
    # 现在result_df包含了从每组重复行中随机选择的一行  
    # print(result_df)
    return result_df
    

#主入口
def auto_test_main(root,my_data,p_disp_Text,select_box):
    #判断串口能否打开
    if not is_port_available(my_data.com_port):
        # messagebox.showinfo("错误", "串口不存在或被占用") 
        p_disp_Text.print_text("串口不存在或被占用")
        # my_data.run_status = False
        return False  
        
    if not is_dir_exist(my_data.directory):
        messagebox.showinfo("错误", "脚本目录不存在")  
        my_data.run_status = False
        return False 
    
    p_disp_Text.print_text("===开始运行===")
    
    ser = None
    phone_device = select_box
    
    if phone_device is not None:
        p_disp_Text.print_text("===连接手机:"+phone_device)
        phone_device = u2.connect(phone_device) #打开USB连接手机.
        p_disp_Text.print_text("===连接手机成功===")
    # 打开串口  
    try:
        ser = serial.Serial(my_data.com_port, my_data.baudrate, timeout=1)  
        p_disp_Text.print_text("===打开串口===")
    except Exception:  
        root.messagebox.showinfo("错误", "串口无法打开")  
        my_data.run_status = False
        return False
    p_disp_Text.print_text("===读取文件===")
    # 读取目录下所有excel  
    file_list = search_dir_files(p_disp_Text,my_data.directory)
    try:
        if ser.isOpen():
            for i in range(int(my_data.loop_count)):
                for item in file_list:
                    p_disp_Text.print_text("===当前文件===:" + item)
                    # 读取Excel文件，假设你想读取第一个sheet（索引为0）  
                    df = pd.read_excel(item, sheet_name=0)  
                    # 获取总行数  
                    num_rows = df.shape[0]  
                    #p_disp_Text.print_text(df.columns)  # 查看所有列名
                    # 相同的"步骤"行只保留一行
                    # print(df)
                    df = filter_duplicate_rows(df)
                    # print(df)
                    
                    ret = excel_pack_parser(p_disp_Text,ser, df, 0, phone_device)

                    if ret == False:
                        ser.close()
                        return False
                    
                    p_disp_Text.print_text("=========================================")
                    
                    if not my_data.run_status:
                        ser.close()
                        p_disp_Text.print_text("+++++总次数+++++:"+ str(my_data.loop_count))
                        p_disp_Text.print_text("+++++当前完成次数:"+str(i+1))
                        return True
                    
                p_disp_Text.print_text("===总次数===:"+ str(my_data.loop_count))
                p_disp_Text.print_text("当前完成次数:"+str(i+1))
                
                now = datetime.now()
                
                p_disp_Text.print_text("时间:"+now.strftime("%H:%M"))
                p_disp_Text.print_text("时间:"+my_data.download_time)
                
                if my_data.download_time == now.strftime("%H:%M"):
                    p_disp_Text.print_text("开始下载固件")
                    download.download_main(my_data.firmware_path)
                    
                    # subprocess.run(  
                    #     [],  # exe文件的路径和参数  
                    #     capture_output=False,  # 捕获输出  
                    #     text=False  # 将输出作为文本（Python 3.7+）  
                    # )
                    # 创建子进程执行外部程序
                    if is_file_exist(my_data.run_exe_path):
                        p_disp_Text.print_text("运行外部程序")
                        process = subprocess.Popen(
                            [my_data.run_exe_path],  # 程序路径和参数列表
                            
                            shell=False,                    # 是否通过shell执行（默认False）
                            cwd=None,                       # 工作目录
                            env=None,                       # 环境变量
                            universal_newlines=False         # 是否将输出作为文本处理
                        )
                    
            # 关闭串口（可选，但在完成通信后关闭它是一个好习惯）  
            ser.close()
            my_data.run_status = False
        else:
            p_disp_Text.print_text("COM打开失败")
            my_data.run_status = False
            return False
    except Exception as e:  
        print(f"An exception occurred: {e}")
        p_disp_Text.print_text("串口错误!!!")

    return True
#结束

#解析EXCEL,封数据包
def excel_pack_parser(p_disp_Text,ser, df, debug, phone_device):
    list_int_data = [126,0,0,0,0,18,0,91,10,0,0,0,0,0,0,0,0,0,0,126]
    # 使用for循环遍历DataFrame的每一行  
    try :
        for index, row in df.iterrows():  
            step = row['步骤']
            if (isinstance(step, int) or isinstance(step, float)) and step > 0:
                p_disp_Text.print_text(f"步骤: {row['步骤']}, 动作: {row['动作']}, X1: {row['X1']}, Y1: {row['Y1']}, X2: {row['X2']}, Y2: {row['Y2']}, 持续: {row['持续时间']}")
                if int(row['设备']) == 1 and phone_device is not None: #手机
                    if(int(row['动作']) == 4):   #点击文本
                        phone_device(text = row['X1']).click()
                    elif (int(row['动作']) == 5):#点击坐标
                        action = phone_device.click(int(row['X1']), int(row['Y1']))
                    if (int(row['动作']) == 6):   #滑动
                        if row['持续时间'] == 0:
                            row['持续时间'] = 50
                        if(row['X1']==row['X2']):
                            row['X1'] += 5
                        duration = row['持续时间']/1000
                        phone_device.swipe(int(row['X1']), int(row['Y1']), int(row['X2']), int(row['Y2']),duration=duration)
                    elif (int(row['动作']) == 7):#输入文本
                        phone_device(className="android.widget.EditText").set_text(text = row['X1'])
                else:   #手表
                    if(row['动作'] == 0):   #使能TP
                        list_int_data[8] = 16
                    if(row['动作'] == 3):   #打开或关闭充电禁用
                        list_int_data[8] = 8
                        list_int_data[9] = int(row['X1']%256)
                    elif (row['动作'] == 2):    #按键
                        list_int_data[8] = 15
                        list_int_data[9] = int(row['X1']%256)
                        list_int_data[10] = int(row['Y1']%256)
                    else:#TP 
                        list_int_data[8] = 17   #操作TP
                        # 封包数据
                        list_int_data[9] = int(row['X1']/256)
                        list_int_data[10] = int(row['X1']%256)
                        list_int_data[11] = int(row['Y1']/256)
                        list_int_data[12] = int(row['Y1']%256)
                        list_int_data[13] = int(row['X2']/256)
                        list_int_data[14] = int(row['X2']%256)
                        list_int_data[15] = int(row['Y2']/256)
                        list_int_data[16] = int(row['Y2']%256)
                        list_int_data[17] = int(row['持续时间']/256)
                        list_int_data[18] = int(row['持续时间']%256)
                        
                    # 发送数据  
                    write_COM(ser, list_int_data)
                # 延时
                if row['持续时间'] == 0:
                    row['持续时间'] = random.randint(100, 1000)
                if row['执行完延时'] == 0:
                    row['执行完延时'] = random.randint(100, 1000)
                delay_ms(row['持续时间'])
                delay_ms(row['执行完延时'])
                if debug == 1:
                    delay_ms(1500)
        return True
    except Exception as e:  
        print(f"An exception occurred: {e}")
        p_disp_Text.print_text("写数据错误!!!")
        return False

# 写数据到串口
def write_COM(ser, list_int_data):
    # 遍历整数列表，将每个整数转换为字节并发送  
    for integer in list_int_data:  
        # 将整数转换为字节（这里假设整数是8位无符号的）  
        byte_data = struct.pack('B', integer)  # 'B' 表示无符号字符  
        
        # 发送字节数据  
        ser.write(byte_data)  

#增加一个毫秒延时函数
def delay_ms(milliseconds):  
    """  
    延时函数，暂停程序的执行指定的毫秒数。  
    """  
    seconds = milliseconds / 1000  
    time.sleep(seconds)  
   
#判断串口是否可以打开
def is_port_available(port):  
    try:  
        ser = serial.Serial(port)  
        ser.close()  
        return True  
    except serial.SerialException:  
        return False 
    
#判断文件是否存在
def is_file_exist(file_path):  
    """  
    判断文件是否存在  
    :param file_path: 文件路径  
    :return: 如果文件存在返回True，否则返回False  
    """  
    return os.path.exists(file_path) and os.path.isfile(file_path)

#判断文件是否存在
def is_dir_exist(file_path):  
    """  
    判断文件是否存在  
    :param file_path: 文件路径  
    :return: 如果文件存在返回True，否则返回False  
    """  
    return os.path.exists(file_path)

def search_dir_files(p_disp_Text,directory):  
    file_list = []
    extensions = ['.xlsx']
    for root, dirs, files in os.walk(directory):  
        for file in files:  
            if not file.startswith('~'):
                if os.path.splitext(file)[1].lower() in extensions:
                    file_list.append(os.path.join(root, file))
    p_disp_Text.print_text(str(file_list))
    return file_list
  

# 如果这个脚本是作为主程序运行（而不是被导入），则调用main函数  
# if __name__ == "__main__":  
#     main()   
    